package com.zlll.winner.service.advertising;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zlll.winner.business.model.advertising.AdvertisingCity;
import com.zlll.winner.business.model.advertising.AdvertisingDetail;
import com.zlll.winner.business.model.advertising.AdvertisingPublish;
import com.zlll.winner.business.model.advertising.AdvertisingSpace;
import com.zlll.winner.business.model.sysUser.SysUser;
import com.zlll.winner.business.service.advertising.IAdvertisingCityService;
import com.zlll.winner.business.service.advertising.IAdvertisingDetailService;
import com.zlll.winner.business.service.advertising.IAdvertisingSpaceService;
import com.zlll.winner.enums.AdvertiseEnum;
import com.zlll.winner.enums.CommonEnum;
import com.zlll.winner.mapper.advertising.AdvertisingDetailMapper;
import com.zlll.winner.mapper.advertising.AdvertisingPublishMapper;
import com.zlll.winner.business.service.advertising.IAdvertisingPublishService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.dubbo.config.annotation.Service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

/**
 * <p>
 * 广告发布表
 * 服务实现类
 * </p>
 *
 * @author qsx
 * @since 2019-09-07
 */
@Service
@Slf4j
public class AdvertisingPublishServiceImpl extends ServiceImpl<AdvertisingPublishMapper, AdvertisingPublish> implements IAdvertisingPublishService {

    @Autowired
    private IAdvertisingSpaceService advertisingSpaceService;
    @Autowired
    private AdvertisingPublishMapper advertisingPublishMapper;
    @Autowired
    private AdvertisingDetailMapper advertisingDetailMapper;
    @Autowired
    private IAdvertisingDetailService advertisingDetailService;
    @Autowired
    private IAdvertisingCityService advertisingCityService;

    /**
     * api接口获取普通广告位信息
     * @param cityName
     * @return
     */
    @Override
    public Object search(String cityName, Integer type) {
        List<AdvertisingSpace> spaceList = advertisingSpaceService.getAdvertisingSpace(type,AdvertiseEnum.CategoryEnum.GENGERAL.val());
        for (AdvertisingSpace space : spaceList) {
            List<AdvertisingPublish> publishes = advertisingPublishMapper.getAdvertisingPublishs(cityName,space.getId());
            if(publishes!=null && publishes.size()>0){
                AdvertisingPublish publish = publishes.get(0);
                List<AdvertisingDetail> details= advertisingDetailService.queryAdvertiseDetailByPublishId(publish.getId());
                publish.setDetails(details);
                space.setPublishList(publishes);
            }
        }
        return spaceList;
    }

    /**
     * 获取轮播广告信息
     * @param cityName
     * @param type
     * @return
     */
    @Override
    public Object searchCarousel(String cityName, Integer type) {
        List<AdvertisingSpace> spaceList = advertisingSpaceService.getAdvertisingSpace(type,AdvertiseEnum.CategoryEnum.CAROUSEL.val());
        List<AdvertisingPublish> publishes = advertisingPublishMapper.getAdvertisingPublishs(cityName,spaceList.get(0).getId());
        if(publishes!=null && publishes.size()>0){
            for(AdvertisingPublish publish : publishes){
                List<AdvertisingDetail> details= advertisingDetailService.queryAdvertiseDetailByPublishId(publish.getId());
                publish.setDetails(details);
            }
        }
        return publishes;
    }

    /**
     * 后端查询广告列表
     * @param spaceId 位置id
     * @param status 状态
     * @param pageNo 页数
     * @param pageSize 每页显示多少条
     * @return
     */
    @Override
    public IPage<Map<String, Object>> findAdvertisePage(Long spaceId, Integer status, String cityCode, Integer type, Integer category, Integer pageNo, Integer pageSize) {
        IPage<Map<String, Object>> page = new Page<>(pageNo,pageSize);
        List<Map<String, Object>> list = advertisingPublishMapper.findAdvertisePage(spaceId, status, cityCode, type, category, page);
        page.setRecords(list);
        return page;
    }

    /**
     * 新增广告
     * @param ad
     * @param details
     * @param citys
     * @param user
     * @return
     */
    @Override
    public boolean addAdPublish(AdvertisingPublish ad, JSONArray details, JSONArray citys, SysUser user) {
        ad.setCreateTime(System.currentTimeMillis());
        ad.setCreateUser(user.getName());
        if (ad.getStatus().equals(AdvertiseEnum.PublishEnum.PUBLISH.val())) {
            ad.setPublisher(user.getName());
        }
        //新增广告记录并返回自增id
        Integer result = advertisingPublishMapper.insert(ad);
        //新增记录为零
        if (result == 0) {
            return true;
        }
        Long id = ad.getId();
        //写入对应的详情表
        List<AdvertisingDetail> advertisingDetails = new ArrayList<>();
        for (int i = 0; i < details.size(); i++) {
            JSONObject json = details.getJSONObject(i);
            if (json.isEmpty()) {
                log.info("广告详情列表的第{}条记录为空", i + 1);
                continue;
            }
            AdvertisingDetail advertisingDetail = json.toJavaObject(AdvertisingDetail.class);
            advertisingDetail.setPublishId(id);
            advertisingDetail.setCreateUser(user.getName());
            advertisingDetail.setCreateTime(System.currentTimeMillis());
            advertisingDetails.add(advertisingDetail);
        }
        if (advertisingDetails!=null && advertisingDetails.size()>0) {
            advertisingDetailService.saveBatch(advertisingDetails);
        }
        //写入对应的广告-项目记录
        if(citys!=null && citys.size()>0){
            List<AdvertisingCity> advertisingProjectArrayList = new ArrayList<>();
            for (int i = 0; i < citys.size(); i++) {
                JSONObject json = citys.getJSONObject(i);
                if (json.isEmpty()) {
                    log.info("广告对应城市的第{}条记录为空", i + 1);
                    continue;
                }
                AdvertisingCity advertisingProject = json.toJavaObject(AdvertisingCity.class);
                advertisingProject.setPublishId(id);
                advertisingProject.setCreateUser(user.getName());
                advertisingProject.setCreateTime(System.currentTimeMillis());
                advertisingProjectArrayList.add(advertisingProject);
            }
            if (advertisingProjectArrayList.size()>0) {
                advertisingCityService.saveBatch(advertisingProjectArrayList);
            }
        }
        return false;
    }

    /**
     * 删除广告
     * @param id
     * @param name
     * @return
     */
    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public int deleteAdVertise(Long id, String name) {
        //删除关联项目
        AdvertisingCity ap = new AdvertisingCity();
        ap.setIsDel(CommonEnum.DelEnum.DEL.val());
        ap.setUpdateUser(name);
        ap.setUpdateTime(System.currentTimeMillis());
        advertisingCityService.update(ap, Wrappers.<AdvertisingCity>lambdaQuery()
                .eq(AdvertisingCity::getPublishId, id));
        //删除关联详情
        AdvertisingDetail al = new AdvertisingDetail();
        al.setIsDel(CommonEnum.DelEnum.DEL.val());
        al.setUpdateTime(System.currentTimeMillis());
        al.setUpdateUser(name);
        advertisingDetailService.update(al, Wrappers.<AdvertisingDetail>lambdaQuery()
                .eq(AdvertisingDetail::getPublishId, id));
        AdvertisingPublish ad = new AdvertisingPublish();
        //删除广告
        ad.setId(id);
        ad.setUpdateUser(name);
        ad.setUpdateTime(System.currentTimeMillis());
        ad.setIsDel(CommonEnum.DelEnum.DEL.val());
        return advertisingPublishMapper.updateById(ad);
    }

    /**
     * 下架操作
     * @param id
     * @param status 状态
     * @param user
     * @return
     */
    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public int updateAdvertiseStatus(Long id, int status, SysUser user) {
        AdvertisingPublish ad = new AdvertisingPublish();
        ad.setId(id);
        ad.setStatus(status);
        ad.setUpdateUser(user.getId().toString());
        ad.setUpdateTime(System.currentTimeMillis());
        return advertisingPublishMapper.updateById(ad);
    }

    /**
     * 获取详情信息
     * @param id
     * @return
     */
    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public Object getPublishTree(Long id) {
        AdvertisingPublish ad = advertisingPublishMapper.selectOne(Wrappers.<AdvertisingPublish>lambdaQuery()
                .eq(AdvertisingPublish::getId, id)
                .eq(AdvertisingPublish::getIsDel, 0));
        List<AdvertisingDetail> adDetail = advertisingDetailService.list(Wrappers.<AdvertisingDetail>lambdaQuery()
                .eq(AdvertisingDetail::getPublishId, id)
                .eq(AdvertisingDetail::getIsDel, 0));
        List<AdvertisingCity> adProjectList = advertisingCityService.list(Wrappers.<AdvertisingCity>lambdaQuery()
                .eq(AdvertisingCity::getPublishId, id)
                .eq(AdvertisingCity::getIsDel, 0));
        Map data = new HashMap<>(3);
        data.put("adInfo", ad);
        data.put("adDetail", adDetail);
        data.put("adProjects", adProjectList);
        return data;
    }

    /**
     * 编辑广告
     * @param ad
     * @param details
     * @param citys
     * @param user
     */
    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public void editAdPublish(AdvertisingPublish ad, JSONArray details, JSONArray citys, SysUser user) {
        ad.setUpdateUser(user.getName());
        ad.setUpdateTime(System.currentTimeMillis());
        if (ad.getStatus().equals(AdvertiseEnum.PublishEnum.PUBLISH.val())) {
            ad.setPublisher(user.getName());
        }
        advertisingPublishMapper.updateById(ad);
        Long adId = ad.getId();
        //更新detail表，先查询再更新
        List<AdvertisingDetail> oldDetailList = advertisingDetailService.list(Wrappers.<AdvertisingDetail>lambdaQuery()
                .eq(AdvertisingDetail::getPublishId, adId)
                .eq(AdvertisingDetail::getIsDel, 0));
        List<AdvertisingDetail> alAdd = new ArrayList<>();
        List<AdvertisingDetail> alUpdate = new ArrayList<>();
        List<AdvertisingDetail> reserved = new ArrayList<>();
        for (int i = 0; i < details.size(); i++) {
            JSONObject json = details.getJSONObject(i);
            if (json.isEmpty()) {
                log.info("广告详情列表的第{}条记录为空", i + 1);
                continue;
            }
            AdvertisingDetail advertisingDetail = json.toJavaObject(AdvertisingDetail.class);
            Long id = advertisingDetail.getId();
            if (id == null) {
                //id为null代表新增的
                advertisingDetail.setCreateUser(user.getName());
                advertisingDetail.setCreateTime(System.currentTimeMillis());
                advertisingDetail.setPublishId(adId);
                alAdd.add(advertisingDetail);
            } else {
                //id不为null代表保留的
                advertisingDetail.setUpdateUser(user.getName());
                advertisingDetail.setUpdateTime(System.currentTimeMillis());
                reserved.add(advertisingDetail);
            }
        }
        if (reserved.size() > 0) {
            AtomicReference<Boolean> exist = new AtomicReference<>(false);
            oldDetailList.forEach(item -> {
                exist.set(true);
                AdvertisingDetail advertisingDetail = null;
                for (int i = 0; i < reserved.size(); i++) {
                    if (item.getId().equals(reserved.get(i).getId())) {
                        advertisingDetail = reserved.get(i);
                        exist.set(false);
                        break;
                    }
                }
                if (exist.get()) {
                    //为true表示这条旧数据不在保留列表中，删掉
                    item.setIsDel(CommonEnum.DelEnum.DEL.val());
                    alUpdate.add(item);
                } else {
                    //为false表示这条这条数据与旧数据匹配，更新
                    alUpdate.add(advertisingDetail);
                }
            });
        } else {        //保留列表为空表示旧数据全清空
            oldDetailList.forEach(item -> {
                item.setIsDel(CommonEnum.DelEnum.DEL.val());
                alUpdate.add(item);
            });
        }
        if (alUpdate.size() > 0) {
            advertisingDetailService.updateBatchById(alUpdate);
        }
        if (alAdd.size() > 0) {
            advertisingDetailService.saveBatch(alAdd);
        }
        //广告对应项目：先查询再更新
        List<AdvertisingCity> oldProjectList = advertisingCityService.list(Wrappers.<AdvertisingCity>lambdaQuery()
                .eq(AdvertisingCity::getPublishId, adId)
                .eq(AdvertisingCity::getIsDel, 0));
        List<AdvertisingCity> adAdd = new ArrayList<>();
        List<AdvertisingCity> adUpdate = new ArrayList<>();
        List<AdvertisingCity> reservedData = new ArrayList<>();
        if(citys!=null && citys.size()>0){
            for (int i = 0; i < citys.size(); i++) {
                JSONObject json = citys.getJSONObject(i);
                if (json.isEmpty()) {
                    log.info("广告对应项目的第{}条记录为空", i + 1);
                    continue;
                }
                AdvertisingCity advertisingProject = json.toJavaObject(AdvertisingCity.class);
                Long id = advertisingProject.getId();
                if (id == null) {
                    //id为null代表新增的
                    advertisingProject.setPublishId(adId);
                    advertisingProject.setCreateTime(System.currentTimeMillis());
                    advertisingProject.setCreateUser(user.getName());
                    adAdd.add(advertisingProject);
                } else {
                    //id不为null代表保留的
                    advertisingProject.setUpdateTime(System.currentTimeMillis());
                    advertisingProject.setUpdateUser(user.getName());
                    reservedData.add(advertisingProject);
                }
            }
        }
        if (reservedData.size() > 0) {
            AtomicReference<Boolean> exist = new AtomicReference<>(false);
            oldProjectList.forEach(item -> {
                exist.set(true);
                for (int i = 0; i < reservedData.size(); i++) {
                    if (item.getId().equals(reservedData.get(i).getId())) {
                        exist.set(false);
                        break;
                    }
                }
                if (exist.get()) {
                    //为true表示这条旧数据不在保留列表中，删掉
                    item.setUpdateTime(System.currentTimeMillis());
                    item.setUpdateUser(user.getName());
                    item.setIsDel(CommonEnum.DelEnum.DEL.val());
                    adUpdate.add(item);
                }
            });
        } else {
            //保留列表为空表示旧数据全清空
            oldProjectList.forEach(item -> {
                item.setUpdateUser(user.getName());
                item.setIsDel(CommonEnum.DelEnum.DEL.val());
                item.setUpdateTime(System.currentTimeMillis());
                adUpdate.add(item);
            });
        }
        if (adUpdate.size() > 0) {
            advertisingCityService.updateBatchById(adUpdate);
        }
        if (adAdd.size() > 0) {
            advertisingCityService.saveBatch(adAdd);
        }
    }
}
